using System;
using System.Collections.Concurrent;
using System.Security.Cryptography;
using System.Text;
using System.Threading;

namespace IppServer.Host.WebUI
{
    /// <summary>
    /// Web管理界面认证管理器
    /// 提供简单的Session管理和密码验证
    /// </summary>
    internal sealed class AuthManager
    {
        private readonly ConcurrentDictionary<string, SessionInfo> _sessions = new ConcurrentDictionary<string, SessionInfo>();
        private readonly Timer _cleanupTimer;
        private const int SessionTimeoutMinutes = 30; // Session超时时间（30分钟）
        private const int CleanupIntervalMinutes = 5; // 清理间隔（5分钟）

        public AuthManager()
        {
            // 定期清理过期Session
            _cleanupTimer = new Timer(CleanupExpiredSessions, null, TimeSpan.FromMinutes(CleanupIntervalMinutes), TimeSpan.FromMinutes(CleanupIntervalMinutes));
        }

        /// <summary>
        /// 验证密码并创建Session
        /// </summary>
        /// <param name="passwordHash">密码哈希</param>
        /// <param name="providedPassword">提供的密码</param>
        /// <param name="allowFirstTimeLogin">是否允许首次登录（需要初始化令牌）</param>
        public string CreateSession(string passwordHash, string providedPassword, bool allowFirstTimeLogin = false)
        {
            if (string.IsNullOrEmpty(passwordHash))
            {
                // 如果没有设置密码，检查是否允许首次登录
                if (!allowFirstTimeLogin)
                {
                    // WebUI不允许首次登录，必须通过GUI设置密码
                    return null;
                }

                // GUI允许首次登录（需要初始化令牌验证）
                if (!Configuration.AdminPasswordInitializer.IsInitialized())
                {
                    // 没有初始化令牌，拒绝登录
                    return null;
                }

                // 有初始化令牌，允许登录（首次登录）
                var sessionId = GenerateSessionId();
                _sessions[sessionId] = new SessionInfo
                {
                    CreatedAt = DateTime.UtcNow,
                    LastAccessAt = DateTime.UtcNow
                };
                return sessionId;
            }

            // 验证密码
            if (!VerifyPassword(providedPassword, passwordHash))
            {
                return null;
            }

            // 创建Session
            var newSessionId = GenerateSessionId();
            _sessions[newSessionId] = new SessionInfo
            {
                CreatedAt = DateTime.UtcNow,
                LastAccessAt = DateTime.UtcNow
            };
            return newSessionId;
        }

        /// <summary>
        /// 验证Session是否有效
        /// </summary>
        public bool ValidateSession(string sessionId)
        {
            if (string.IsNullOrEmpty(sessionId))
            {
                return false;
            }

            if (!_sessions.TryGetValue(sessionId, out var session))
            {
                return false;
            }

            // 检查是否过期
            if (DateTime.UtcNow - session.LastAccessAt > TimeSpan.FromMinutes(SessionTimeoutMinutes))
            {
                _sessions.TryRemove(sessionId, out _);
                return false;
            }

            // 更新最后访问时间
            session.LastAccessAt = DateTime.UtcNow;
            return true;
        }

        /// <summary>
        /// 删除Session（登出）
        /// </summary>
        public void RemoveSession(string sessionId)
        {
            if (!string.IsNullOrEmpty(sessionId))
            {
                _sessions.TryRemove(sessionId, out _);
            }
        }

        /// <summary>
        /// 从Cookie中提取Session ID
        /// </summary>
        public string GetSessionIdFromCookie(string cookieHeader)
        {
            if (string.IsNullOrEmpty(cookieHeader))
            {
                return null;
            }

            var cookies = cookieHeader.Split(';');
            foreach (var cookie in cookies)
            {
                var parts = cookie.Trim().Split('=');
                if (parts.Length == 2 && parts[0].Trim().Equals("ipp_admin_session", StringComparison.OrdinalIgnoreCase))
                {
                    return parts[1].Trim();
                }
            }
            return null;
        }

        /// <summary>
        /// 生成密码哈希（SHA256）
        /// </summary>
        public static string HashPassword(string password)
        {
            if (string.IsNullOrEmpty(password))
            {
                return null;
            }

            using (var sha256 = SHA256.Create())
            {
                var bytes = Encoding.UTF8.GetBytes(password);
                var hash = sha256.ComputeHash(bytes);
                return Convert.ToBase64String(hash);
            }
        }

        /// <summary>
        /// 验证密码
        /// </summary>
        private static bool VerifyPassword(string password, string passwordHash)
        {
            if (string.IsNullOrEmpty(password) || string.IsNullOrEmpty(passwordHash))
            {
                return false;
            }

            var computedHash = HashPassword(password);
            return string.Equals(computedHash, passwordHash, StringComparison.Ordinal);
        }

        /// <summary>
        /// 生成Session ID
        /// </summary>
        private static string GenerateSessionId()
        {
            var bytes = new byte[32];
            using (var rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(bytes);
            }
            return Convert.ToBase64String(bytes).Replace("+", "-").Replace("/", "_").Replace("=", "");
        }

        /// <summary>
        /// 清理过期的Session
        /// </summary>
        private void CleanupExpiredSessions(object state)
        {
            var now = DateTime.UtcNow;
            var expiredSessions = new System.Collections.Generic.List<string>();

            foreach (var kvp in _sessions)
            {
                if (now - kvp.Value.LastAccessAt > TimeSpan.FromMinutes(SessionTimeoutMinutes))
                {
                    expiredSessions.Add(kvp.Key);
                }
            }

            foreach (var sessionId in expiredSessions)
            {
                _sessions.TryRemove(sessionId, out _);
            }
        }

        public void Dispose()
        {
            _cleanupTimer?.Dispose();
            _sessions.Clear();
        }

        private sealed class SessionInfo
        {
            public DateTime CreatedAt { get; set; }
            public DateTime LastAccessAt { get; set; }
        }
    }
}

